﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Resources;
using AppRPG.Properties;

namespace AppRPG
{
    public class FileMapManager
    {
        private static Dictionary<string, Image> _dictionary;

        static FileMapManager()
        {
            _dictionary = new Dictionary<string, Image>();
        }

        static public List<PhysObject.PhysObject> LoadPhysicalObjects(string path)
        {
            StreamReader file = new StreamReader(path);
            string line;
            List<string> allLines = new List<string>();
            while ((line = file.ReadLine()) != null)
            {
                if (line != string.Empty)
                    allLines.Add(line);
            }
            List<PhysObject.PhysObject> loadPhysicalObjects = new List<PhysObject.PhysObject>();
            for (int i = 0; i < allLines.Count; i += 5)
            {
                string trim0 = allLines[i].Replace("name:", string.Empty).Trim('[', ']');
                string trim = allLines[i + 1].Replace("type:", string.Empty).Trim('[', ']');
                string trim1 = allLines[i + 2].Replace("position:", string.Empty).Trim('[', ']');
                string trim2 = allLines[i + 3].Replace("size:", string.Empty).Trim('[', ']');
                string trim3 = allLines[i + 4].Replace("texture:", string.Empty).Trim('[', ']');
                loadPhysicalObjects.Add(FoundType(trim0, trim, GetSize(trim2), ParserLine(trim1), LoadTextureFromAssembly(trim3)));
            }
            return loadPhysicalObjects;
        }


        static private PhysObject.PhysObject FoundType(string namePhysObject, string nameType, Size size, Point position, Image texture)
        {
            Type type = Type.GetType(nameType);
            if (type != null)
            {
                ConstructorInfo constructorInfo = type.GetConstructor(new[] { typeof(string), typeof(Point), typeof(Size), typeof(Image)});
                return (PhysObject.PhysObject)constructorInfo.Invoke(new object[] { namePhysObject, position, size, texture });
            }
            return null;
        }

        static private Size GetSize(string line)
        {
            return new Size(ParserLine(line));
        }

        private static Image LoadTextureFromAssembly(string nameTexture)
        {
            if (_dictionary.ContainsKey(nameTexture))
            {
                return _dictionary[nameTexture];
            }
            ResourceManager resourceManager =
                new ResourceManager("AppRPG.Properties.Resources", typeof(Resources).Assembly);
            Image image;
            if (nameTexture != string.Empty)
            {
                image = (Image) resourceManager.GetObject(nameTexture);
            }
            else
            {
                image = Resources.EmptyTexture;
            }
            image.Tag = nameTexture;
            _dictionary.Add(nameTexture, image);
            return image;
        }

        public static Image LoadTexture(string path)
        {
            Image image = Image.FromFile(path);
            int lastIndex = path.LastIndexOf(@"\");
            string temp = path.Remove(0, lastIndex + 1);
            lastIndex = temp.LastIndexOf('.');
            image.Tag = temp.Remove(lastIndex);
            return image;
        }

        static private Point ParserLine(string line)
        {
            int positionX = 0;
            string temp = string.Empty;
            foreach (var letter in line)
            {
                if (letter != ' ')
                {
                    temp += letter;
                }
                else
                {
                    positionX = int.Parse(temp);
                    temp = string.Empty;
                }
            }
            int positionY = int.Parse(temp);
            return new Point(positionX, positionY);
        }

        static private string FoundName(Image texture)
        {
            foreach (var key in _dictionary.Keys)
            {
                if (_dictionary[key] == texture)
                    return key;
            }
            return "EmptyGameObject";
        }

        public static List<PhysObject.PhysObject> LoadConfiguration()
        {
            string path = @"Configure.txt";
            List<PhysObject.PhysObject> loadPhysicalObjects = new List<PhysObject.PhysObject>();
            StreamReader file = new StreamReader(path);
            string line;
            while ((line = file.ReadLine()) != null)
            {
                if (line != string.Empty)
                {
                    Resources.EmptyTexture.Tag = "EmptyTexture";
                    loadPhysicalObjects.Add(FoundType("GameObject", line, new Size(100, 100), new Point(100, 100),
                        (Image) (Resources.EmptyTexture)));
                }
            }
            return loadPhysicalObjects;
        }

        static public void SavePhysicalObjectsToFile(List<PhysObject.PhysObject> physicalObjects, string pathFile = "Безымянный.txt")
        {
            StreamWriter file = new StreamWriter(pathFile, append: false);
            {
                foreach (var physicalObject in physicalObjects)
                {
                    file.WriteLine("name:" + "[" + physicalObject.GetObjectName() + "]");
                    file.WriteLine("type:" + "[" + physicalObject.GetType() + "]");
                    file.WriteLine("position:" + "[" + physicalObject.GetPosition().X + " " + physicalObject.GetPosition().Y + "]");
                    file.WriteLine("size:" + "[" + physicalObject.GetDimension().Width + " " + physicalObject.GetDimension().Height + "]");
                    file.WriteLine("texture:" + "[" + (string)physicalObject.GetTexture().Tag + "]");
                    file.WriteLine();
                }
                file.Close();
            }
        }
    }
}
